//===============================================================================
// Q4Tech Engineering Team
// Mobile Updater Application Block - November 2006
//===============================================================================
// Copyright  Q4Tech Informatica Argentina.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.Runtime.InteropServices;

namespace Ipc
{
  /// <summary>
  /// Summary description for PointToPointMessageQueueHelper.
  /// </summary>
  public class PointToPointMessageQueueHelper
  {
    public static IntPtr CreateMessageQueue(string queueName, bool readAccess)
    {
        return CreateMsgQueue(queueName, new MsgQueueOptions(readAccess));
    }

    public static IntPtr OpenMessageQueue(IntPtr hProcess, IntPtr originalQueueHandle, bool readAccess)
    {
      return OpenMsgQueue(hProcess, originalQueueHandle, new MsgQueueOptions(readAccess));
    }

    public static bool CloseMessageQueue(IntPtr queueHandle)
    {
      return CloseMsgQueue(queueHandle);
    }

    public static bool ReadMessageQueue(IntPtr queueHandle, byte[] buffer)
    {
      int bytesRead, flags;
      return ReadMsgQueue(queueHandle, buffer, buffer.Length, out bytesRead, 0, out flags);
    }

    public static bool WriteMessageQueue(IntPtr queueHandle, byte[] buffer, int length)
    {
      return WriteMsgQueue(queueHandle, buffer, length, 0, 0);
    }

    #region API declarations
    public static IntPtr INVALID_HANDLE = IntPtr.Zero;

    public const uint TIMEOUT_INFINITE = 0xFFFFFFFF;

    [DllImport("coredll.dll")]
    private static extern IntPtr CreateMsgQueue(string lpszName, MsgQueueOptions lpOptions);

    [DllImport("coredll.dll")]
    private static extern bool GetMsgQueueInfo(IntPtr hMsgQ, out MsgQueueInfo lpInfo);
      
    [DllImport("coredll.dll")]
    private static extern IntPtr OpenMsgQueue(IntPtr hSrcProc, IntPtr hMsgQ, MsgQueueOptions lpOptions);                                                                                                                                                                                         

    [DllImport("coredll.dll")]
    private static extern bool ReadMsgQueue(IntPtr hMsgQ, byte[] lpBuffer, int cbBufferSize, out int lpNumberOfBytesRead, int dwTimeout, out int pdwFlags);

    [DllImport("coredll.dll")]
    private static extern bool WriteMsgQueue(IntPtr hMsgQ, byte[] lpBuffer, int cbDataSize, int dwTimeout, int dwFlags);

    [DllImport("coredll.dll")]
    private static extern bool CloseMsgQueue(IntPtr hMsgQ);

    [DllImport("coredll.dll")]
    public static extern Int32 WaitForSingleObject(IntPtr hHandle,uint dwMilliseconds);

    private class MsgQueueInfo
    {
      public int dwSize;
      public int dwFlags;
      public int dwMaxMessages;
      public int cbMaxMessage;
      public int dwCurrentMessages;
      public int dwMaxQueueMessages;
      public short wNumReaders;
      public short wNumWriters;
    }

    private class MsgQueueOptions
    {
      private const int MSGQUEUE_ALLOW_BROKEN = 0x02;
      public MsgQueueOptions(bool readAccess)
      {
        dwSize = Marshal.SizeOf(typeof(MsgQueueOptions));
        dwFlags = MSGQUEUE_ALLOW_BROKEN; 
        dwMaxMessages = 20;
        cbMaxMessage = 100;
        bReadAccess = Convert.ToInt32(readAccess);
      }
      public int dwSize;
      public int dwFlags;
      public int dwMaxMessages;
      public int cbMaxMessage;
      public int bReadAccess;
    }
    #endregion
  }
}